package com.xianyun.book.common.core.handle;

import com.alibaba.cola.catchlog.CatchAndLog;
import com.alibaba.cola.domain.ApplicationContextHelper;
import com.alibaba.cola.exception.BizException;
import lombok.extern.slf4j.Slf4j;
import java.util.Arrays;
import java.util.List;

/**
 * @author macos-zyj
 */
@CatchAndLog
@Slf4j
public class HandleChainFactory {
    public static<T,Q> HandleChain<T,Q> buildHandleChain(Class... handleClsList) {
        if (null!= handleClsList && handleClsList.length>0){
            Class[] interfaceArray = handleClsList[0].getInterfaces();
            List<Class> interfaceList = Arrays.asList(interfaceArray);
            if (interfaceList.contains(SingleHandle.class)&&
                    interfaceList.contains(MultipleHandle.class)){
                throw new BizException("SYS_CONFIG_ERROR","请不要一起实现Single和Multiple这个两个接口");
            }else {
                if (interfaceList.contains(SingleHandle.class)){
                    return singleHandel(handleClsList);
                }
                if (interfaceList.contains(MultipleHandle.class)){
                    return multipleHandel(handleClsList);
                }
            }
        }
        throw new BizException("SYS_CONFIG_ERROR","系统配置错误");
    }
    private static <T,Q> HandleChain<T,Q> singleHandel(Class... queryClsList) {
        SingleInvoker last = new SingleInvoker(){};
        HandleChain<T, Q> handleChain = new HandleChain<>();
        for(int i = queryClsList.length - 1; i >= 0; i--){
            SingleInvoker<T,Q> next = last;
            SingleHandle<T,Q> singleHandle ;
            try {
                singleHandle = (SingleHandle<T,Q>) ApplicationContextHelper.getBean(queryClsList[i]);
                last = new SingleInvoker<T,Q>(){
                    @Override
                    public T invoke(HandleParam<Q> handleParam) {
                        return singleHandle.doQuery(handleParam, next);
                    }
                };
                handleChain.setHeader(last);
            }catch (Exception e){
                throw new RuntimeException("链式执行配置有误");
            }
        }
        return handleChain;
    }

    private static <T,Q> HandleChain<T,Q> multipleHandel(Class... queryClsList) {
        MultipleInvoker last = new MultipleInvoker(){};
        HandleChain<T, Q> handleChain = new HandleChain<>();
        for(int i = queryClsList.length - 1; i >= 0; i--){
            MultipleInvoker<T,Q> next = last;
            MultipleHandle<T,Q> multipleHandle;
            try {
                multipleHandle = (MultipleHandle<T,Q>) ApplicationContextHelper.getBean(queryClsList[i]);
                last = new MultipleInvoker<T,Q>(){
                    @Override
                    public List<T> invokeList(HandleParam<Q> handleParam) {
                        return multipleHandle.doListQuery(handleParam,next);
                    }
                };
                handleChain.setHeader(last);
            }catch (Exception e){
                throw new RuntimeException("链式执行配置有误");
            }
        }
        return handleChain;
    }
}
